package com.lagou.framework.container;

import com.lagou.framework.common.HttpServlet;
import com.lagou.framework.common.Request;
import com.lagou.framework.common.Response;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author srh
 * @date 2020/04/03
 **/

public class Context {

    private static final String WEB_INF = "WEB-INF";
    private static final String WEB_XML = "web.xml";

    /**
     * 绝对路径
     */
    private String absolutePath;
    /**
     * 应用名
     */
    private String contextName;

    private Map<String, HttpServlet> servletMap;

    public void init(String path) {
        this.absolutePath = path;
        this.servletMap = parseWebXmlConfig(path);
    }

    private Map<String, HttpServlet> parseWebXmlConfig(String path) {
        Map<String, HttpServlet> mappings = new HashMap<>(16);
        try {
            InputStream config = new FileInputStream(String.format("%s/%s/%s", path, WEB_INF, WEB_XML));
            SAXReader saxReader = new SAXReader();
            Document root = saxReader.read(config);
            Element rootElement = root.getRootElement();
            List<Element> nodes = rootElement.selectNodes("//servlet");
            for (Element element : nodes) {
                String servletName = element.selectSingleNode("servlet-name").getStringValue();
                String servletClass = element.selectSingleNode("servlet-class").getStringValue();
                Element node = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                String urlPatten = node.selectSingleNode("url-pattern").getStringValue();
                HttpServlet instance = getInstance(path, servletClass);
                mappings.put(urlPatten, instance);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return mappings;
    }

    private HttpServlet getInstance(String path, String servletClass) throws Exception {
        URL[] url = {new URL(String.format("%s%s/", "file://", path))};
        URLClassLoader classLoader = new URLClassLoader(url);
        return (HttpServlet) classLoader.loadClass(servletClass).newInstance();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Context)) {
            return false;
        }
        Context context = (Context) o;
        return Objects.equals(absolutePath, context.absolutePath) &&
                Objects.equals(contextName, context.contextName) &&
                Objects.equals(servletMap, context.servletMap);
    }

    @Override
    public int hashCode() {
        return Objects.hash(absolutePath, contextName, servletMap);
    }

    public void doService(Request request, Response response) throws IOException {
        for (Map.Entry<String, HttpServlet> entry : servletMap.entrySet()) {
            if (request.getUrl().endsWith(entry.getKey())) {
                entry.getValue().service(request, response);
            }
        }
    }

    public static void main(String[] args) throws MalformedURLException, ClassNotFoundException {
        String name = "com.lagou.demo2.servlet.DemoServlet2";
        URL[] url = {new URL("file://" + "/Users/srh/Desktop/webapps/demo2/")};
        URLClassLoader loader = new URLClassLoader(url);
        Class<?> aClass = loader.loadClass(name);
        System.out.println();
    }
}
